package com.sbtr.controller;

import com.sbtr.business.calibration.service.*;
import com.sbtr.business.classify.service.IClassifyService;
import com.sbtr.common.PageDto;
import com.sbtr.common.Response;
import com.sbtr.constant.CalibrationConstant;
import com.sbtr.constant.ProjectConstant;
import com.sbtr.impl.CalibrationPictureCommon;
import com.sbtr.impl.CalibrationVoiceCommon;
import com.sbtr.impl.MaterialInfoCommon;
import com.sbtr.open.calibration.dto.*;
import com.sbtr.open.classify.dto.ClassifyDto;
import com.sbtr.open.material.dto.MaterialInfoDto;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;
import java.util.List;

/**
 * 标注任务模块
 */
@RestController
@RequestMapping("/calibration")
//@Api(tags = "标注任务模块（包括标注任务发布+已接收任务的标注等接口）")
@ApiIgnore
public class CalibrationController {
    private static final String REGEX = "；"; //分隔符，中文分号
    private static final Logger logger = LoggerFactory.getLogger(CalibrationController.class);
    private static final String[] DETECTION_ARR = {ProjectConstant.PROJECT_TYPE_IMG_DETECTION};
    private static final String[] CLASSIFY_ARR = {ProjectConstant.PROJECT_TYPE_IMG_CLASSIFY};
    private static final String[] SPEC_ARR = {ProjectConstant.PROJECT_TYPE_VOICE_CLASSIFY};
    private static final String[] TXT_ARR = {ProjectConstant.PROJECT_TYPE_TXT_CLASSIFY};
    @Autowired
    CalibrationPictureCommon calibrationPictureCommon;
    @Autowired
    ICalibrationVoiceService calibrationVoiceService;
    @Autowired
    CalibrationVoiceCommon calibrationVoiceCommon;
    @Autowired
    private ICalibrationService calibrationService;
    @Autowired
    private ICalibrationDetailsService calibrationDetailService;
    @Autowired
    private ICalibrationRecordDailyService calibrationRecordDailyService;
    @Autowired
    private ICalibrationTxtEntityService calibrationTxtEntityService;
    @Autowired
    private ICalibrationTxtEntityMapService calibrationTxtEntityMapService;
    @Autowired
    private ICalibrationTxtService calibrationTxtService;
    @Autowired
    private ICalibrationImgService calibrationImgService;
    @Autowired
    private ICalibrationObjectDetectionService calibrationImgDetectService;
    @Autowired
    private IClassifyService classifyService;
    @Value("${oss.config.samplePath}")
    private String samplePath;
    @Autowired
    private MaterialInfoCommon materialInfoCommon;//
    @Value("${oss.config.uploadPath}")
    private String uploadPath;

    /**
     * 分页查询我发布的任务列表
     * 1.查询当前有效的，以“任务创建者名称”进行查询，
     * 2.支持 "标注任务名称"、"创建者"、"标注状态"、“优先级”、“任务类型”、“标注素材数量”、“标签数量”等属性进行查询
     *
     * @return
     */
    @ApiOperation(value = "分页查询我发布的任务", notes = "分页查询我发布的任务", httpMethod = "POST")
    @PostMapping(value = "/search")
    public Response<PageDto<CalibrationDto>> search(@RequestBody CalibrationSearchDto dto) {
        return Response.success(calibrationService.search(dto));
    }


    /**
     * 数据标注模块：
     * 分页查询我被分配的任务
     * 1.以任务完成者名称进行查询（任务完成者是在开始时候进行任务分配进行选择的。
     * 2.以 “任务完成者名称 ”进行查询
     *
     * @param dto
     * @return
     */
    @ApiOperation(value = "分页查询我被分配的任务", notes = "分页查询我被分配的任务", httpMethod = "POST")
    @PostMapping(value = "/search-details")
    public Response<PageDto<CalibrationDetailsDto>> searchDetails(@RequestBody CalibrationSearchDetailsDto dto) {
        return Response.success(calibrationDetailService.searchDetails(dto));
    }

    /**
     * 查看数据标注我发布的信息详情
     *
     * @param dto
     * @return
     */
    @ApiOperation(value = "查询我发布的任务的明细详情（新原型的标注人员列表）", notes = "查询我发布的任务的明细详情", httpMethod = "POST")
    @PostMapping(value = "/search-details-by-calibrationId")
    public Response<PageDto<CalibrationDetailsDto>> searchDetailsByCalibrationId(
            @RequestBody CalibrationSearchByDetailsDto dto) {
        return Response.success(calibrationDetailService.searchDetailsByCalibrationId(dto));
    }

    @ApiOperation(value = "查询发布任务的今日排行榜", notes = "查询发布任务的今日排行榜", httpMethod = "POST")
    @PostMapping(value = "/search-calibration-record-daily/{calibrationId}")
    public Response<List<CalibrationRecordDailyDto>> searchCalibrationRecordDaily(
            @PathVariable("calibrationId") Long calibrationId, @RequestParam("rusultNum") Long resultNum
    ) {
        return Response.success(calibrationRecordDailyService.searchCalibrationRecordDaily(calibrationId, resultNum));
    }

    @ApiOperation(value = "查询发布任务的累计排行榜", notes = "查询发布任务的累计排行榜", httpMethod = "POST")
    @PostMapping(value = "/search-calibration-record-all/{calibrationId}")
    public Response<List<CalibrationRecordDailyDto>> searchCalibrationRecordAll(
            @PathVariable("calibrationId") Long calibrationId, @RequestParam("rusultNum") Long resultNum
    ) {
        return Response.success(calibrationRecordDailyService.searchCalibrationRecordAll(calibrationId, resultNum));
    }

    @ApiOperation(value = "查询接受任务最近7天的标注进度", notes = "查询接受任务最近7天的标注进度", httpMethod = "POST")
    @PostMapping(value = "/search-calibration-record/{calibrationDetailId}")
    public Response<List<CalibrationRecordDailyDto>> searchCalibrationRecord(
            @PathVariable("calibrationDetailId") Long calibrationDetailId
    ) {
        return Response.success(calibrationRecordDailyService.searchCalibrationRecord(calibrationDetailId));
    }

    @ApiOperation(value = "分页查询未标注文本素材", notes = "分页查询未标注文本素材", httpMethod = "POST")
    @PostMapping(value = "/get-txt-no-details")
    public Response<PageDto<CalibrationTxtDto>> getTxtNoDetails(@RequestBody CalibrationSearchByDetailsDto dto) {
        return Response.success(calibrationTxtService.getTxtNoDetails(dto));
    }

    @ApiOperation(value = "分页查询已标注文本素材", notes = "分页查询已标注文本素材", httpMethod = "POST")
    @PostMapping("/get-txt-details")
    public Response<PageDto<CalibrationTxtDto>> getTxtDetails(@RequestBody CalibrationSearchByDetailsDto dto) {
        return Response.success(calibrationTxtService.getTxtDetails(dto));
    }

    @ApiOperation(value = "查询已标注各标签文本素材数量", notes = "查询已标注各标签文本素材数量", httpMethod = "POST")
    @PostMapping("/count-txt-hascalibrated")
    public Response<List<CalibrationCountByClassifyDto>> countHasCalibrated(@RequestBody CalibrationSearchByDetailsDto dto) {
        return Response.success(calibrationTxtService.countHasCalibrated(dto));
    }

    @ApiOperation(value = "分页查询图片未标注数据或已标注某类数据", notes = "查询标定集数据", httpMethod = "POST")
    @PostMapping("/get-img-calibrate")
    public Response<PageDto<CalibrationImgDto>> getImgCalibrate(@RequestBody CalibrationSearchByDetailsDto dto) {
        return Response.success(calibrationImgService.getImgCalibrate(dto));
    }

    @ApiOperation(value = "查询已标注图像的各标签数量", notes = "查询已标注图像的各标签数量", httpMethod = "POST")
    @PostMapping("/count-img-hascalibrated")
    public Response<List<CalibrationCountByClassifyDto>> countImgHasCalibrated(@RequestParam("calibrationDetailsId") Long calibrationDetailsId) {
        return Response.success(calibrationImgService.countImgHasCalibrated(calibrationDetailsId));
    }

    @ApiOperation(value = "分页查询声音未标注数据或已标注某类数据", notes = "查询标定集数据", httpMethod = "POST")
    @PostMapping("/get-voice-calibrate")
    public Response<PageDto<CalibrationVoiceDto>> getVoiceCalibrate(@RequestBody CalibrationSearchByDetailsDto dto) {
        return Response.success(calibrationVoiceService.getVoiceCalibrate(dto));
    }

    @ApiOperation(value = "查询已标注声音的各标签数量", notes = "查询已标注声音的各标签数量", httpMethod = "POST")
    @PostMapping("/count-voice-hascalibrated")
    public Response<List<CalibrationCountByClassifyDto>> countVoiceHasCalibrated(@RequestParam("calibrationDetailsId") Long calibrationDetailsId) {
        return Response.success(calibrationVoiceService.countVoiceHasCalibrated(calibrationDetailsId));
    }

    @ApiOperation(value = "分页查询物体检测de图片列表", notes = "分页查询物体检测de图片列表", httpMethod = "POST")
    @PostMapping("/get-img-detect-calibrate")
    public Response<PageDto<CalibrationImgDetectDto>> getImgDetectCalibrate(@RequestBody CalibrationSearchByDetailsDto dto) {
        return Response.success(calibrationImgDetectService.getImgDetectList(dto));
    }

    @ApiOperation(value = "查询物体检测已标注的各标签数量", notes = "查询物体检测已标注的各标签数量", httpMethod = "GET")
    @RequestMapping(value = "/loadImgDetectCalibrationAllLabels", method = RequestMethod.GET)
    @ResponseBody
    public Response<List<ClassifyDto>> loadImgDetectCalibrationAllLabels(@RequestParam("calibrationDetailsId") Long calibrationDetailsId) {
        List<ClassifyDto> labels = calibrationImgDetectService.loadImgDetectCalibrationAllLabels(calibrationDetailsId);

        return Response.success(labels);
    }

    @ApiOperation(value = "分页查询文本实体未标注数据或已标注数据", notes = "查询标定集数据", httpMethod = "POST")
    @PostMapping("/get-txt-entity-calibrate")
    public Response<PageDto<CalibrationTxtEntityDto>> getTxtEntityCalibrate(@RequestBody CalibrationSearchByDetailsDto dto) {
        return Response.success(calibrationTxtEntityService.getTxtEntityCalibrate(dto));
    }

    //不使用，改用http路径
    @Deprecated
    @ApiOperation(value = "根据图片id获取下载预览素材图片", notes = "根据图片id获取下载预览素材图片", httpMethod = "GET")
    @RequestMapping(value = "/material-picture/download/{id}", method = RequestMethod.GET)
    public void downloadPicture(@PathVariable("id") Long id,
                                @RequestParam(name = "thumbnail") boolean thumbnail, HttpServletResponse response) {
        CalibrationImgDto calibrationImgDto = calibrationImgService.findById(id);
        String picDir = calibrationImgDto.getPictureDir();
        if (thumbnail) {
            picDir = calibrationImgDto.getThumbnailDir();
        }
        try {
            InputStream fis = calibrationPictureCommon.readFile(picDir);
//            response.setContentType("image/png");
            response.setHeader("Cache-Control", "max-age=31536000");// 让浏览器缓存图片,要在流关闭前设置
            byte[] buff = new byte[1024 * 8];
            int len;
            while ((len = fis.read(buff)) != -1) {
                response.getOutputStream().write(buff, 0, len);
            }
            fis.close();
        } catch (Exception e) {
            logger.error("下载文件异常", e);
        }
    }

    //不使用，改用http路径
    @Deprecated
    @ApiOperation(value = "根据图片id获取下载播放素材音频", notes = "根据图片id获取下载播放素材音频", httpMethod = "GET")
    @RequestMapping(value = "/material-voice/download/{id}", method = RequestMethod.GET)
    public void downloadVoice(@PathVariable("id") Long id,
                              HttpServletResponse response) {
        CalibrationVoiceDto calibrationVoiceDto = calibrationVoiceService.findById(id);
        String picDir = calibrationVoiceDto.getVoiceDir();
        try {
            InputStream fis = calibrationVoiceCommon.readFile(picDir);
            response.setHeader("Cache-Control", "max-age=31536000");// 让浏览器缓存图片,要在流关闭前设置
            byte[] buff = new byte[1024 * 8];
            int len;
            while ((len = fis.read(buff)) != -1) {
                response.getOutputStream().write(buff, 0, len);
            }
            fis.close();
        } catch (Exception e) {
            logger.error("下载文件异常", e);
        }
    }

    @ApiOperation(value = "查询个人标定进度", notes = "查询个人标定进度", httpMethod = "POST")
    @PostMapping(value = "/search-progress-by-finisher")
    public Response<CalibrationProgressDto> searchProgressByFinisher(
            @RequestBody CalibrationSearchByDetailsDto dto) {
        return Response.success(calibrationDetailService.searchProgressByFinisher(dto));
    }

    @ApiOperation(value = "根据发布任务id查询标签", notes = "根据发布任务id查询标签", httpMethod = "GET")
    @GetMapping(value = "/search-by-id")
    public Response<List<ClassifyDto>> searchById(@RequestParam("calibrationId") Long calibrationId) {
        logger.info("根据接收任务id查询：{}", calibrationId);
        return Response.success(classifyService.search(calibrationId));
    }

    /**
     * 1.进行批量关联性逻辑删除，仅仅修改isAvailable属性参数为0
     * 2.并修改详发布任务详细信息列表为无效
     *
     * @param idList
     * @return
     */
    @ApiOperation(value = "根据id集合批量删除我发布的任务", notes = "根据id集合批量删除我发布的任务", httpMethod = "DELETE")
    @RequestMapping(value = "/batch", method = RequestMethod.DELETE)
    public Response<Boolean> batchDeleteById(@RequestParam("idList") List<Long> idList) {
        boolean b = calibrationService.batchDeleteById(idList);
        if (b) {
            return Response.success("删除成功", b);
        } else {
            return Response.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), "删除失败");
        }
    }


    @ApiOperation(value = "新增或修改", notes = "新增或修改标注任务", httpMethod = "POST")
    @PostMapping(value = "/save")
    public Response<CalibrationDto> saveCallibration(@RequestBody CalibrationDto dto) {
        if (dto.getId() == null) {
//            dto.setCreater(UserUtils.getFdLoginName());
            dto.setCreateTime(new Date());
        }
        dto.setUpdateTime(new Date());
        return Response.success("保存成功", calibrationService.save(dto));
    }

    /**
     * 上传标注素材
     * 1.解压素材，并上传到对应目录
     * 2.生成缩率图，并数据库存储相关信息
     * 3.根据任务分配情况，存储标注数据详细信息到对应表单
     * 4.支持在已有任务基础上进行"添加数据"功能
     *
     * @param id
     * @param file
     * @param finisher
     * @return
     */
    @ApiOperation(value = "上传标注任务相关的素材", notes = "上传标注任务相关的素材", httpMethod = "POST")
    @RequestMapping(value = "/upload/{id}", method = RequestMethod.POST, headers = "content-type=multipart/form-data")
    public Response<CalibrationDto> upload(
            @PathVariable("id") Long id,//标注任务id
            @RequestPart(value = "File") MultipartFile file,
            @RequestParam(value = "finisher", required = false) String finisher) {

        if (file.isEmpty() || file.getSize() == 0) {
            return Response.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), "文件不能为空");
        }
        try {

            CalibrationDto calibrationDto = calibrationService.findById(id);
            String taskType = calibrationDto.getTaskType();

            // 1图像分类，单类别
            if (StringUtils.endsWithAny(taskType, CalibrationConstant.PROJECT_TYPE_IMG_CLASSIFY)) {
                return Response.success(materialInfoCommon.saveImageData(calibrationDto, file, finisher));
                // 2声音分类
            } else if (StringUtils.endsWithAny(taskType, CalibrationConstant.PROJECT_TYPE_VOICE_CLASSIFY)) {
                return Response.success(materialInfoCommon.saveVoiceData(calibrationDto, file, finisher));
                // 3文本分类模式
            } else if (StringUtils.endsWithAny(taskType, CalibrationConstant.PROJECT_TYPE_TXT_CLASSIFY)) {
                return Response.success(materialInfoCommon.saveTxtData(calibrationDto, file, finisher));
                // 4图像检测
            } else if (StringUtils.endsWithAny(taskType, CalibrationConstant.PROJECT_TYPE_IMG_DETECTION)) {
                return Response.success(materialInfoCommon.saveImageDectionData(calibrationDto, file, finisher));
                // 文本检测-无使用
            } else if (StringUtils.endsWithAny(taskType, CalibrationConstant.PROJECT_TYPE_TXT_ENTITY)) {
                return Response.success(materialInfoCommon.saveTxtEntity(calibrationDto, file, finisher));
            }
        } catch (Exception e) {
            e.printStackTrace();
            return Response.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), "上传失败:" + e.getMessage());
        }
        return null;
    }

//    @ApiOperation(value = "物体检测任务，给单个图片打标签", notes = "图片圈出物体打标签", httpMethod = "POST")
//    @Deprecated
//    @RequestMapping(value = "/{id}/save_object_detection_label", method = RequestMethod.POST)
//    public Response<CalibrationObjectDetectionDto> saveObjectDetectionLabel(@PathVariable("id") Long calibrationId,
//                                                                      @RequestBody CalibrationObjectDetectionDto dto) {
//        return Response.success(calibrationService.saveObjectDetectionLabel(calibrationId, dto));
//    }


    @ApiOperation(value = "批量保存文本标定数据", notes = "批量保存文本标定数据", httpMethod = "POST")
    @RequestMapping(value = "/{id}/save-txt-details", method = RequestMethod.POST)
    public Response<List<CalibrationTxtDto>> saveTxtDetails(@PathVariable("id") Long calibrationDetailsId,
                                                            @RequestBody List<CalibrationTxtDto> dtos) {
        return Response.success(calibrationService.saveTxtDetails(calibrationDetailsId, dtos));
    }

    @ApiOperation(value = "批量保存图片标定数据", notes = "批量保存图片标定数据", httpMethod = "POST")
    @RequestMapping(value = "/{id}/save-img-calibrate", method = RequestMethod.POST)
    public Response<List<CalibrationImgDto>> saveImgCalibrate(@PathVariable("id") Long calibrationDetailsId,
                                                              @RequestBody List<CalibrationImgDto> dtos) {
        return Response.success(calibrationImgService.saveImgCalibrate(calibrationDetailsId, dtos));
    }

    @ApiOperation(value = "单个保存文本实体的标签", notes = "单个保存文本实体的标签", httpMethod = "POST")
    @RequestMapping(value = "/{id}/save-txt-entity-labels", method = RequestMethod.POST)
    public Response<CalibrationTxtEntityMapDto> saveTxtEntityLabels(@PathVariable("id") Long calibrationDetailsId,
                                                                    @RequestBody CalibrationTxtEntityMapDto dto) {
        return Response.success(calibrationTxtEntityMapService.saveTxtEntityLabels(calibrationDetailsId, dto));
    }

    @ApiOperation(value = "批量保存文本实体的标签", notes = "批量保存文本实体的标签", httpMethod = "POST")
    @RequestMapping(value = "/{id}/batch-save-txt-entity-labels", method = RequestMethod.POST)
    public Response<List<CalibrationTxtEntityMapDto>> batchSaveTxtEntityLabels(@PathVariable("id") Long calibrationDetailsId,
                                                                               @RequestBody List<CalibrationTxtEntityMapDto> dtos) {
        return Response.success(calibrationTxtEntityMapService.batchSaveTxtEntityLabels(calibrationDetailsId, dtos));
    }

    @ApiOperation(value = "文本实体中，获取一行文本上的所有标签和实体信息", notes = "文本实体中，获取一行文本上的所有标签和实体信息", httpMethod = "GET")
    @RequestMapping(value = "/loadOneTxtEntityLabels", method = RequestMethod.GET)
    public Response<List<CalibrationTxtEntityMapDto>> loadOneTxtEntityLabels(@RequestParam("txtId") Long txtId) {
        return Response.success(calibrationTxtEntityMapService.loadOneTxtEntityLabels(txtId));
    }

    @ApiOperation(value = "单个保存物体检测的标签", notes = "单个保存物体检测的标签", httpMethod = "POST")
    @RequestMapping(value = "/{picId}/save-img-detect-labels", method = RequestMethod.POST)
    public Response<CalibrationObjectDetectionDto> saveLabel(@PathVariable("picId") Long picId,
                                                             @RequestBody CalibrationObjectDetectionDto dto) {
        return Response.success(calibrationImgDetectService.save(dto));
    }

    @ApiOperation(value = "批量保存物体检测的标签", notes = "批量保存物体检测的标签", httpMethod = "POST")
    @RequestMapping(value = "/{picId}/batch-save-img-detect-labels", method = RequestMethod.POST)
    public Response<List<CalibrationObjectDetectionDto>> batchSaveImgDetectLabels(@PathVariable("picId") Long picId,
                                                                                  @RequestBody List<CalibrationObjectDetectionDto> dtos) {
        return Response.success(calibrationImgDetectService.batchSaveLabel(dtos, picId));
    }

    @ApiOperation(value = "单个删除物体检测的标签", notes = "单个删除物体检测的标签", httpMethod = "POST")
    @RequestMapping(value = "/delete-img-detect-label", method = RequestMethod.POST)
    public Response<Boolean> deleteLable(@RequestBody CalibrationObjectDetectionDto dto) {
        return Response.success(calibrationImgDetectService.deleteLable(dto));
    }

    @ApiOperation(value = "批量保存图片跳过数据", notes = "批量保存图片跳过数据", httpMethod = "POST")
    @RequestMapping(value = "/{id}/save-img-skip", method = RequestMethod.POST)
    public Response<List<CalibrationImgDto>> saveImgSkip(@PathVariable("id") Long calibrationDetailsId,
                                                         @RequestBody List<CalibrationImgDto> dtos) {
        return Response.success(calibrationImgService.saveImgSkip(calibrationDetailsId, dtos));
    }

    @ApiOperation(value = "图片检测中，获取一张图片上的所有标签和框框坐标信息", notes = "图片检测中，获取一张图片上的所有标签和框框坐标信息", httpMethod = "GET")
    @RequestMapping(value = "/loadOnePicLabels", method = RequestMethod.GET)
    public Response<List<CalibrationObjectDetectionDto>> loadOnePicLabels(@RequestParam("picId") String picId) {
        return Response.success(calibrationImgDetectService.loadOnePicLabels(picId));
    }

//    @RequestMapping(value = "deleteLable", method = RequestMethod.GET)
//    @ResponseBody
//    public Response<String> deleteLable(@RequestParam("calibrationId") String calibrationId,@RequestParam("picId") String picId,@RequestParam("classifyId") String classifyId){
//        return Response.success(calibrationImgDetectService.deleteLable(calibrationId,picId,classifyId));
//    }

    @RequestMapping(value = "/queryPicByLabelId", method = RequestMethod.GET)
    @ResponseBody
    public Response<List<CalibrationImgDetectDto>> queryPicByLabelId(@RequestParam("classifyId") String classifyId) {
        return Response.success(calibrationImgDetectService.queryPicByLabelId(classifyId));
    }

    @ApiOperation(value = "批量保存声音标定数据", notes = "批量保存声音标定数据", httpMethod = "POST")
    @RequestMapping(value = "/{id}/save-voice-calibrate", method = RequestMethod.POST)
    public Response<List<CalibrationVoiceDto>> saveVoiceCalibrate(@PathVariable("id") Long calibrationDetailsId,
                                                                  @RequestBody List<CalibrationVoiceDto> dtos) {
        return Response.success(calibrationVoiceService.saveVoiceCalibrate(calibrationDetailsId, dtos));
    }

    @ApiOperation(value = "批量保存声音跳过数据", notes = "批量保存声音跳过数据", httpMethod = "POST")
    @RequestMapping(value = "/{id}/save-voice-skip", method = RequestMethod.POST)
    public Response<List<CalibrationVoiceDto>> saveVoiceSkip(@PathVariable("id") Long calibrationDetailsId,
                                                             @RequestBody List<CalibrationVoiceDto> dtos) {
        return Response.success(calibrationVoiceService.saveVoiceSkip(calibrationDetailsId, dtos));
    }


    /**
     * 数据标注，下载模板
     *
     * @param taskType
     * @param resp
     */
    @ApiOperation(value = "获取文件url", notes = "获取文件url", httpMethod = "POST")
    @RequestMapping(value = "/downloadExample", method = RequestMethod.POST)
    @ResponseBody
    public void downloadExample(@RequestParam("taskType") String taskType,
                                HttpServletResponse resp) {
        OutputStream out;
        // 读取本地文件的输入流
        InputStream in;
        if (StringUtils.endsWithAny(taskType, CalibrationConstant.PROJECT_TYPE_TXT_CLASSIFY)) { // 文本分类模式
            try {
                File file = new File(samplePath + File.separator + "text_calibration.zip");
                in = new FileInputStream(file);
                // 设置响应正文的MIME类型
//                resp.setContentType("Content-Disposition;charset=UTF-8");
                resp.setContentType("application/octet-stream");

                resp.setHeader("Content-Disposition", "attachment;" + " filename=" + "text_calibration.zip");
                out = resp.getOutputStream();// 把本地文件发送给客户端
                int byteRead = 0;
                byte[] buffer = new byte[512];
                while ((byteRead = in.read(buffer)) != -1) {
                    out.write(buffer, 0, byteRead);
                }
                in.close();
                out.flush();
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            // 文本检测
        } else if (StringUtils.endsWithAny(taskType, CalibrationConstant.PROJECT_TYPE_TXT_ENTITY)) {
            try {
                File file = new File(samplePath + File.separator + "text_entity_calibration.zip");
                in = new FileInputStream(file);
                // 设置响应正文的MIME类型
//                resp.setContentType("Content-Disposition;charset=UTF-8");
                resp.setContentType("application/octet-stream");

                resp.setHeader("Content-Disposition", "attachment;" + " filename=" + "image_dection_calibration.zip");
                out = resp.getOutputStream();// 把本地文件发送给客户端
                int byteRead = 0;
                byte[] buffer = new byte[512];
                while ((byteRead = in.read(buffer)) != -1) {
                    out.write(buffer, 0, byteRead);
                }
                in.close();
                out.flush();
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            // 图像检测
        } else if (StringUtils.endsWithAny(taskType, CalibrationConstant.PROJECT_TYPE_IMG_DETECTION)) {
            try {
//				in = minioUtil.getObject("data", "data.zip");
                File file = new File(samplePath + File.separator + "image_dection_calibration.zip");
                in = new FileInputStream(file);
                // 设置响应正文的MIME类型
//                resp.setContentType("Content-Disposition;charset=UTF-8");
                resp.setContentType("application/octet-stream");

                resp.setHeader("Content-Disposition", "attachment;" + " filename=" + "image_dection_calibration.zip");
                // 把本地文件发送给客户端
                out = resp.getOutputStream();
                int byteRead = 0;
                byte[] buffer = new byte[512];
                while ((byteRead = in.read(buffer)) != -1) {
                    out.write(buffer, 0, byteRead);
                }
                in.close();
                out.flush();
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            // 声音分类
        } else if (StringUtils.endsWithAny(taskType, CalibrationConstant.PROJECT_TYPE_VOICE_CLASSIFY)) {
            try {
//				in = minioUtil.getObject("voice", "voice.zip");
                File file = new File(samplePath + File.separator + "voice_calibration.zip");
                in = new FileInputStream(file);
                // 设置响应正文的MIME类型
//                resp.setContentType("Content-Disposition;charset=UTF-8");
                resp.setContentType("application/octet-stream");

                resp.setHeader("Content-Disposition", "attachment;" + " filename=" + "voice_calibration.zip");
                // 把本地文件发送给客户端
                out = resp.getOutputStream();
                int byteRead = 0;
                byte[] buffer = new byte[512];
                while ((byteRead = in.read(buffer)) != -1) {
                    out.write(buffer, 0, byteRead);
                }
                in.close();
                out.flush();
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            // 图像分类，单类别
        } else if (StringUtils.endsWithAny(taskType, CalibrationConstant.PROJECT_TYPE_IMG_CLASSIFY)) {
            try {
                File file = new File(samplePath + File.separator + "image_calibration.zip");
                in = new FileInputStream(file);
                // 设置响应正文的MIME类型
//                resp.setContentType("Content-Disposition;charset=UTF-8");
                resp.setContentType("application/octet-stream");

                resp.setHeader("Content-Disposition", "attachment;" + " filename=" + "image_calibration.zip");
                // 把本地文件发送给客户端
                out = resp.getOutputStream();
                int byteRead = 0;
                byte[] buffer = new byte[512];
                while ((byteRead = in.read(buffer)) != -1) {
                    out.write(buffer, 0, byteRead);
                }
                in.close();
                out.flush();
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 生成建模数据
     *
     * @param dto
     * @return
     */
    @ApiOperation(value = "生成我的数据集", notes = "生成我的数据集,必须前端校验好，有标注才有这操作按钮", httpMethod = "POST")
    @RequestMapping(value = "/{id}/generateCalibrationData", method = RequestMethod.POST)
    @ResponseBody
    public Response<Boolean> generateCalibrationData(@RequestBody GenerateDataDto dto) {
        CalibrationDto calibrationDto = calibrationService.findById(dto.getCalibrationId());
        String taskType = calibrationDto.getTaskType();
        MaterialInfoDto dtos = new MaterialInfoDto();
        if (StringUtils.endsWithAny(taskType, CalibrationConstant.PROJECT_TYPE_IMG_CLASSIFY)) { // 图像分类，单类别
            dtos = materialInfoCommon.generateImageData(calibrationDto, dto);
        } else if (StringUtils.endsWithAny(taskType, CalibrationConstant.PROJECT_TYPE_VOICE_CLASSIFY)) { // 声音分类
            dtos = materialInfoCommon.generateVoiceData(calibrationDto, dto);
        } else if (StringUtils.endsWithAny(taskType, CalibrationConstant.PROJECT_TYPE_TXT_CLASSIFY)) { // 文本分类模式
            dtos = materialInfoCommon.generateTxtData(calibrationDto, dto);
        } else if (StringUtils.endsWithAny(taskType, CalibrationConstant.PROJECT_TYPE_IMG_DETECTION)) { // 图像检测
            dtos = materialInfoCommon.generateImageDectionData(calibrationDto, dto);
        } else if (StringUtils.endsWithAny(taskType, CalibrationConstant.PROJECT_TYPE_TXT_ENTITY)) { // 文本检测
            dtos = materialInfoCommon.generateTxtEntityData(calibrationDto, dto);
        }
        if (dtos != null) {
            return Response.success(true);
        } else {
            return Response.success(false);
        }

    }

    /**
     * 下载当前标定的数据信息
     *
     * @param calibrationId
     * @param resp
     */
    @ApiOperation(value = "下载标定的数据", notes = "下载标定的数据", httpMethod = "POST")
    @RequestMapping(value = "/{id}/createCalibrationData", method = RequestMethod.POST)
    @ResponseBody
    public void createCalibrationData(@PathVariable("id") Long calibrationId,
                                      HttpServletResponse resp
    ) {
        CalibrationDto calibrationDto = calibrationService.findById(calibrationId);
        String taskType = calibrationDto.getTaskType();
        OutputStream out;
        // 读取本地文件的输入流
        InputStream in;

        if (StringUtils.endsWithAny(taskType, CalibrationConstant.PROJECT_TYPE_IMG_CLASSIFY)) {
            String resultFilePath = materialInfoCommon.createImageData(calibrationDto);
            File file = new File(resultFilePath);
            try {
                in = new FileInputStream(file);
                // 设置响应正文的MIME类型
//                resp.setContentType("Content-Disposition;charset=UTF-8");
                resp.setContentType("application/octet-stream");

                resp.setHeader("Content-Disposition", "attachment;" + " filename=" + file.getName());
                // 把本地文件发送给客户端
                out = resp.getOutputStream();
                int byteRead = 0;
                byte[] buffer = new byte[512];
                while ((byteRead = in.read(buffer)) != -1) {
                    out.write(buffer, 0, byteRead);
                }
                in.close();
                out.flush();
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else if (
                StringUtils.endsWithAny(taskType, CalibrationConstant.PROJECT_TYPE_VOICE_CLASSIFY)
        ) {
            String resultFilePath = materialInfoCommon.createVoiceData(calibrationDto);
            File file = new File(resultFilePath);

            try {
                in = new FileInputStream(file);
                // 设置响应正文的MIME类型
//                resp.setContentType("Content-Disposition;charset=UTF-8");
                resp.setContentType("application/octet-stream");

                resp.setHeader("Content-Disposition", "attachment;" + " filename=" + file.getName());
                // 把本地文件发送给客户端
                out = resp.getOutputStream();
                int byteRead = 0;
                byte[] buffer = new byte[512];
                while ((byteRead = in.read(buffer)) != -1) {
                    out.write(buffer, 0, byteRead);
                }
                in.close();
                out.flush();
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else if (
                StringUtils.endsWithAny(taskType, CalibrationConstant.PROJECT_TYPE_TXT_CLASSIFY)
        ) {
            File file = materialInfoCommon.createTxtData(calibrationDto);
            try {
                in = new FileInputStream(file);
                // 设置响应正文的MIME类型
//                resp.setContentType("Content-Disposition;charset=UTF-8");
                resp.setContentType("application/octet-stream");

                resp.setHeader("Content-Disposition", "attachment;" + " filename=" + file.getName());
                // 把本地文件发送给客户端
                out = resp.getOutputStream();
                int byteRead = 0;
                byte[] buffer = new byte[512];
                while ((byteRead = in.read(buffer)) != -1) {
                    out.write(buffer, 0, byteRead);
                }
                in.close();
                out.flush();
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }

        } else if (StringUtils.endsWithAny(taskType, CalibrationConstant.PROJECT_TYPE_IMG_DETECTION)) {//图片检测下载已标注的素材数据
            //查询总任务（发布任务）的标注图片并生成zip文件
            File file = materialInfoCommon.createImageDectionData(calibrationDto);

            //下载
            try {
                in = new FileInputStream(file);
                // 设置响应正文的MIME类型
//                resp.setContentType("Content-Disposition;charset=UTF-8");
                resp.setHeader("Content-Disposition", "attachment;" + " filename=" + file.getName());
                // 把本地文件发送给客户端
                out = resp.getOutputStream();
                int byteRead = 0;
                byte[] buffer = new byte[1024];
                while ((byteRead = in.read(buffer)) != -1) {
                    out.write(buffer, 0, byteRead);
                }
                in.close();
                out.flush();
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else if (
                StringUtils.endsWithAny(taskType, CalibrationConstant.PROJECT_TYPE_TXT_ENTITY)
        ) {
            File file = materialInfoCommon.createTxtEntityData(calibrationDto);

            try {
                in = new FileInputStream(file);
                // 设置响应正文的MIME类型
//                resp.setContentType("Content-Disposition;charset=UTF-8");
                resp.setHeader("Content-Disposition", "attachment;" + " filename=" + file.getName());
                // 把本地文件发送给客户端
                out = resp.getOutputStream();
                int byteRead = 0;
                byte[] buffer = new byte[512];
                while ((byteRead = in.read(buffer)) != -1) {
                    out.write(buffer, 0, byteRead);
                }
                in.close();
                out.flush();
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 标注信息详情查看--->根据标注任务ID，下载个人标定数据文件功能
     *
     * @param calibrationId
     * @param finisher
     * @param resp
     */
    @ApiOperation(value = "下载个人标定的数据", notes = "下载个人标定的数据", httpMethod = "POST")
    @RequestMapping(value = "/{id}/createCalibrationDetailsData", method = RequestMethod.POST)
    @ResponseBody
    public void createCalibrationDetailsData(
            @PathVariable("id") Long calibrationId,
            @RequestParam(value = "finisher", required = true) String finisher,
            HttpServletResponse resp) {

        CalibrationDto calibrationDto = calibrationService.findById(calibrationId);
        String taskType = calibrationDto.getTaskType();
        OutputStream out;
        // 读取本地文件的输入流
        InputStream in;
        // 图像分类，单类别
        if (StringUtils.endsWithAny(taskType, CalibrationConstant.PROJECT_TYPE_IMG_CLASSIFY)) {
            String resultFilePath = materialInfoCommon.createImageDetailsData(calibrationDto, finisher);
            File file = new File(resultFilePath);
            try {
                in = new FileInputStream(file);
                // 设置响应正文的MIME类型
//                resp.setContentType("Content-Disposition;charset=UTF-8");
                resp.setContentType("application/octet-stream");

                resp.setHeader("Content-Disposition", "attachment;" + " filename=" + file.getName());
                // 把本地文件发送给客户端
                out = resp.getOutputStream();
                int byteRead = 0;
                byte[] buffer = new byte[512];
                while ((byteRead = in.read(buffer)) != -1) {
                    out.write(buffer, 0, byteRead);
                }
                in.close();
                out.flush();
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            // 声音分类
        } else if (StringUtils.endsWithAny(taskType, CalibrationConstant.PROJECT_TYPE_VOICE_CLASSIFY)) {
            String resultFilePath = materialInfoCommon.createVoiceDetailsData(calibrationDto, finisher);
            File file = new File(resultFilePath);
            try {
                in = new FileInputStream(file);
                // 设置响应正文的MIME类型
//                resp.setContentType("Content-Disposition;charset=UTF-8");
                resp.setContentType("application/octet-stream");

                resp.setHeader("Content-Disposition", "attachment;" + " filename=" + file.getName());
                // 把本地文件发送给客户端
                out = resp.getOutputStream();
                int byteRead = 0;
                byte[] buffer = new byte[512];
                while ((byteRead = in.read(buffer)) != -1) {
                    out.write(buffer, 0, byteRead);
                }
                in.close();
                out.flush();
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else if (
                StringUtils.endsWithAny(taskType, CalibrationConstant.PROJECT_TYPE_TXT_CLASSIFY)
        ) {
            File file = materialInfoCommon.createTxtDetailsData(calibrationDto, finisher);

            try {
                in = new FileInputStream(file);
                // 设置响应正文的MIME类型
//                resp.setContentType("Content-Disposition;charset=UTF-8");
                resp.setHeader("Content-Disposition", "attachment;" + " filename=" + file.getName());
                // 把本地文件发送给客户端
                out = resp.getOutputStream();
                int byteRead = 0;
                byte[] buffer = new byte[512];
                while ((byteRead = in.read(buffer)) != -1) {
                    out.write(buffer, 0, byteRead);
                }
                in.close();
                out.flush();
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else if (StringUtils.endsWithAny(taskType, CalibrationConstant.PROJECT_TYPE_IMG_DETECTION)) {
            //查询个人任务（子任务的图片）并生成zip文件
            File file = materialInfoCommon.createImageDectionData(calibrationDto, finisher);

            //下载
            try {
                in = new FileInputStream(file);
                // 设置响应正文的MIME类型
//                resp.setContentType("Content-Disposition;charset=UTF-8");
                resp.setContentType("application/octet-stream");

                resp.setHeader("Content-Disposition", "attachment;" + " filename=" + file.getName());
                // 把本地文件发送给客户端
                out = resp.getOutputStream();
                int byteRead = 0;
                byte[] buffer = new byte[512];
                while ((byteRead = in.read(buffer)) != -1) {
                    out.write(buffer, 0, byteRead);
                }
                in.close();
                out.flush();
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
//            finally {
//                //下载完就删除？？？
//            }
        } else if (StringUtils.endsWithAny(taskType, CalibrationConstant.PROJECT_TYPE_TXT_ENTITY)) {
            File file = materialInfoCommon.createTxtEntityDetailsData(calibrationDto, finisher);
            try {
                in = new FileInputStream(file);
                // 设置响应正文的MIME类型
//                resp.setContentType("Content-Disposition;charset=UTF-8");
                resp.setHeader("Content-Disposition", "attachment;" + " filename=" + file.getName());
                // 把本地文件发送给客户端
                out = resp.getOutputStream();
                int byteRead = 0;
                byte[] buffer = new byte[512];
                while ((byteRead = in.read(buffer)) != -1) {
                    out.write(buffer, 0, byteRead);
                }
                in.close();
                out.flush();
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}
